##// END OF EJS Templates
added pdf template
added pdf template

File last commit:

r6:9626d775d625 default
r8:8cd05144ebee default
Show More
iic.c
319 lines | 10.0 KiB | text/x-c | CLexer
/*------------------------------------------------------------------------------
-- This file is a part of the libuc, microcontroler library
-- Copyright (C) 2011, Alexis Jeandet
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-------------------------------------------------------------------------------
-- Author : Alexis Jeandet
-- Mail : alexis.jeandet@gmail.com
-------------------------------------------------------------------------------*/
#include "iic.h"
#include "core.h"
#define iicputdata(iicdev,W,IICONSET,IICONCLR) (iicdev)->I2DAT = (W);\
(iicdev)->I2CONSET = (IICONSET);\
(iicdev)->I2CONCLR = (IICONCLR);
#define iicgetdata(iicdev,W,IICONSET,IICONCLR) (W) = (iicdev)->I2DAT;\
(iicdev)->I2CONSET = (IICONSET);\
(iicdev)->I2CONCLR = (IICONCLR);
i2ctrl i2cwrite2(i2cDev* dev,char address,char*cmd,int* cmdcnt,char*data,int* datcnt)
{
char iicdat=0;
dev->I2CONCLR = 0x28;
iicdat = (address<<1) & 0xFE;
int count = (*datcnt) + 2;
*datcnt = 0;
while(dev->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout
dev->I2CONSET = (1<<5); //initiate transfert
while(count>0)
{
while((dev->I2CONSET & 0x08)!=0x08);
switch(dev->I2STAT)
{
case 0x08:
iicputdata(dev,iicdat,(1<<2),0x28);
iicdat = *cmd++;
break;
case 0x10:
iicputdata(dev,iicdat,(1<<2),0x28);
iicdat = *cmd++;
*cmdcnt = (*cmdcnt) - 1;
break;
case 0x18:
iicputdata(dev,iicdat,0,0x08);
if((*cmdcnt)>1)
{
iicdat = *cmd++;
*cmdcnt = (*cmdcnt) - 1;
}
else
{
count--;
iicdat = *data++;
}
break;
case 0x28:
iicputdata(dev,iicdat,(1<<2),0x08);
if((*cmdcnt)>1)
{
iicdat = *cmd++;
*cmdcnt = (*cmdcnt) - 1;
}
else
{
count--;
*datcnt = (*datcnt)+1;
iicdat = *data++;
}
break;
case 0x20:
count = 0;
break;
case 0x30:
count = 0;
break;
case 0x38:
count = 0;
break;
default:
break;
}
}
dev->I2CONSET = (1<<4) + (1<<2);
dev->I2CONCLR = 1<<3;
return i2noerr;
}
i2ctrl i2cwrite(i2cDev* dev,char address,char*data,int* cnt)
{
char iicdat=0;
dev->I2CONCLR = 0x28;
iicdat = (address<<1) & 0xFE;
int count = (*cnt) + 1;
*cnt = 0;
while(dev->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout
dev->I2CONSET = (1<<5); //initiate transfert
while(count>0)
{
while((dev->I2CONSET & 0x08)!=0x08);
switch(dev->I2STAT)
{
case 0x08:
iicputdata(dev,iicdat,(1<<2),0x28);
iicdat = *data++;
break;
case 0x10:
iicputdata(dev,iicdat,(1<<2),0x28);
iicdat = *data++;
break;
case 0x18:
iicputdata(dev,iicdat,0,0x08);
count--;
iicdat = *data++;
break;
case 0x28:
iicputdata(dev,iicdat,(1<<2),0x08);
*cnt = (*cnt)+1;
count--;
iicdat = *data++;
break;
case 0x20:
return i2noack;
count = 0;
break;
case 0x30:
return i2noack;
count = 0;
break;
case 0x38:
return i2arbloss;
count = 0;
break;
default:
break;
}
}
dev->I2CONSET = (1<<4) + (1<<2);
dev->I2CONCLR = 1<<3;
return i2noerr;
}
i2ctrl i2cread(i2cDev* dev,char address,char*data,int* cnt)
{
char iicdat=0;
dev->I2CONCLR = 0x28;
iicdat = (address<<1) + 1;
int count = (*cnt) + 1;
*cnt = 0;
while(dev->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout
dev->I2CONSET = (1<<5); //initiate transfert
while(count>0)
{
while((dev->I2CONSET & 0x08)!=0x08);
switch(dev->I2STAT)
{
case 0x08:
iicputdata(dev,iicdat,(1<<2),0x28);
break;
case 0x10:
iicputdata(dev,iicdat,(1<<2),0x28);
break;
case 0x40:
dev->I2CONSET = (1<<2);
dev->I2CONCLR = (1<<3);
count--;
break;
case 0x50:
iicgetdata(dev,iicdat,(1<<2),(1<<3));
count--;
*cnt = (*cnt) + 1;
*data++ = iicdat;
break;
case 0x48:
return i2noack;
break;
case 0x58:
count = 0;
return i2noack;
break;
default:
break;
}
}
dev->I2CONSET = (1<<4) + (1<<2);
dev->I2CONCLR = 1<<3;
return i2noerr;
}
void i2csetup(i2cDev* dev,int clkH,int clkL)
{
dev->I2CONCLR = 0x6C;
dev->I2SCLH = clkH;
dev->I2SCLL = clkL;
dev->I2CONSET = 1<<6; //enable I2C block
dev->I2CONCLR = 0x28;
}
void i2cenable(i2cDev* dev)
{
dev->I2CONSET = 1<<6;
}
void i2cdisable(i2cDev* dev)
{
dev->I2CONCLR = (1<<6);
}
i2cDev* i2copen(int count){
i2cDev* dev;
switch(count)
{
case 0:
dev = (i2cDev*)((unsigned long)LPC_I2C0_BASE);
break;
case 1:
dev = (i2cDev*)((unsigned long)LPC_I2C1_BASE);
break;
case 2:
dev = (i2cDev*)((unsigned long)LPC_I2C2_BASE);
break;
default:
dev = (i2cDev*)0;
break;
}
return dev;
}
unsigned char i2cgetpclkfactor(i2cDev* dev)
{
unsigned int clksel=0;
const char clkselDec[]={4,1,2,8};
switch((int)dev)
{
case (int)LPC_I2C0_BASE:
clksel = (LPC_SC->PCLKSEL0>>14) & 3;
break;
case (int)LPC_I2C1_BASE:
clksel = (LPC_SC->PCLKSEL1>>6) & 3;
break;
case (int)LPC_I2C2_BASE:
clksel = (LPC_SC->PCLKSEL1>>20) & 3;
break;
default:
break;
}
return clkselDec[clksel];
}
void i2csetpclkfactor(i2cDev* dev,unsigned char pclkfactor)
{
const char clkselDec[]={1,1,2,2,0,0,0,0,3};
unsigned int clksel=0;
switch((int)dev)
{
case (int)LPC_I2C0_BASE:
LPC_SC->PCLKSEL0 |= clkselDec[pclkfactor]<<14;
LPC_SC->PCLKSEL0 &= clkselDec[pclkfactor]<<14;
break;
case (int)LPC_I2C1_BASE:
LPC_SC->PCLKSEL1 |= clkselDec[pclkfactor]<<6;
LPC_SC->PCLKSEL1 &= clkselDec[pclkfactor]<<6;
break;
case (int)LPC_I2C2_BASE:
LPC_SC->PCLKSEL1 |= clkselDec[pclkfactor]<<20;
LPC_SC->PCLKSEL1 &= clkselDec[pclkfactor]<<20;
break;
default:
break;
}
}
void i2csetdatarate(i2cDev* dev,unsigned int dataRate)
{
unsigned int pclk = 0;
unsigned int cpuclk=0;
unsigned int i2csclkl=0;
if(dev==0)return;
cpuclk = coregetCpuFreq();
pclk = cpuclk / i2cgetpclkfactor(dev);
i2csclkl = (pclk / dataRate)>>1;
if(i2csclkl<4) i2csclkl = 4;
i2csetup(dev,i2csclkl,i2csclkl);
}