##// END OF EJS Templates
Libuc make templates extracted from main script, to make it more modular
Libuc make templates extracted from main script, to make it more modular

File last commit:

r6:9626d775d625 default
r7:16404fe7ec6c 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);
}