##// END OF EJS Templates
LFR's Leon3 target added and and tested with simple hello world.
LFR's Leon3 target added and and tested with simple hello world.

File last commit:

r12:cc0fb1c881c0 default
r13:8ca866292111 default
Show More
iic.c
350 lines | 11.2 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) {((_i2cDev)(iicdev))->I2DAT = (W);\
((_i2cDev)(iicdev))->I2CONSET = (IICONSET);\
((_i2cDev)(iicdev))->I2CONCLR = (IICONCLR);}
#define iicgetdata(iicdev,W,IICONSET,IICONCLR) {(W) = ((_i2cDev)(iicdev))->I2DAT;\
((_i2cDev)(iicdev))->I2CONSET = (IICONSET);\
((_i2cDev)(iicdev))->I2CONCLR = (IICONCLR);}
i2ctrl i2cwrite2(i2cDev dev,char address,char*cmd,int* cmdcnt,char*data,int* datcnt)
{
char iicdat=0;
((_i2cDev)dev)->I2CONCLR = 0x28;
iicdat = (address<<1) & 0xFE;
int count = (*datcnt) + 2;
(*datcnt) = 0;
while(((_i2cDev)dev)->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout
((_i2cDev)dev)->I2CONSET = (1<<5); //initiate transfert
while(count>0)
{
while((((_i2cDev)dev)->I2CONSET & 0x08)!=0x08);
switch(((_i2cDev)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:
return i2noack;
count = 0;
break;
case 0x30:
return i2noack;
count = 0;
break;
case 0x38:
return i2arbloss;
count = 0;
break;
default:
break;
}
}
((_i2cDev)dev)->I2CONSET = (1<<4) + (1<<2);
((_i2cDev)dev)->I2CONCLR = 1<<3;
return i2noerr;
}
i2ctrl i2cwrite(i2cDev dev,char address,char*data,int* cnt)
{
char iicdat=0;
((_i2cDev)dev)->I2CONCLR = 0x28;
iicdat = (address<<1) & 0xFE;
int count = (*cnt) + 1;
*cnt = 0;
while(((_i2cDev)dev)->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout
((_i2cDev)dev)->I2CONSET = (1<<5); //initiate transfert
while(count>0)
{
while((((_i2cDev)dev)->I2CONSET & 0x08)!=0x08);
switch(((_i2cDev)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;
}
}
((_i2cDev)dev)->I2CONSET = (1<<4) + (1<<2);
((_i2cDev)dev)->I2CONCLR = 1<<3;
return i2noerr;
}
i2ctrl i2cread(i2cDev dev,char address,char*data,int* cnt)
{
char iicdat=0;
((_i2cDev)dev)->I2CONCLR = 0x28;
iicdat = (address<<1) + 1;
unsigned int count = (*cnt);
*cnt = 0;
while(((_i2cDev)dev)->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout
((_i2cDev)dev)->I2CONSET = (1<<5); //initiate transfert
while(count!=0)
{
while((((_i2cDev)dev)->I2CONSET & 0x08)!=0x08);
switch(((_i2cDev)dev)->I2STAT)
{
while((((_i2cDev)dev)->I2CONSET & (1<<3))!=(1<<3));
case 0x08:
iicputdata(dev,iicdat,(1<<2),0x28);
break;
case 0x10:
iicputdata(dev,iicdat,(1<<2),0x28);
break;
case 0x40:
if((count!=1)) ((_i2cDev)dev)->I2CONSET = (1<<2);
else ((_i2cDev)dev)->I2CONCLR = (1<<2);
((_i2cDev)dev)->I2CONCLR = 1<<3;
break;
case 0x50:
if((count==2)) iicgetdata(dev,iicdat,(0),(0x0c))
else iicgetdata(dev,iicdat,(4),(8))
count--;
*cnt = (*cnt) + 1;
*data = iicdat;
data++;
break;
case 0x48:
((_i2cDev)dev)->I2CONSET = 0x14;
((_i2cDev)dev)->I2CONCLR = 8;
return i2noerr;
break;
case 0x58:
iicgetdata(dev,iicdat,(0x14),(8));
count--;
*cnt = (*cnt) + 1;
*data = iicdat;
data++;
return i2noerr;
break;
default:
break;
}
}
((_i2cDev)dev)->I2CONSET = (1<<4);
((_i2cDev)dev)->I2CONCLR =(1<<2);
((_i2cDev)dev)->I2CONCLR = 1<<3;
return i2noerr;
}
void i2csetup(i2cDev dev,int clkH,int clkL)
{
((_i2cDev)dev)->I2CONCLR = 0x6C;
((_i2cDev)dev)->I2SCLH = clkH;
((_i2cDev)dev)->I2SCLL = clkL;
((_i2cDev)dev)->I2CONSET = 1<<6; //enable I2C block
((_i2cDev)dev)->I2CONCLR = 0x28;
}
void i2cenable(i2cDev dev)
{
((_i2cDev)dev)->I2CONSET = 1<<6;
}
void i2cdisable(i2cDev dev)
{
((_i2cDev)dev)->I2CONCLR = (1<<6);
}
i2cDev i2copen(int count){
i2cDev dev;
switch(count)
{
case 0:
dev = (i2cDev)((unsigned long)I2C0_BASE_ADDR);
break;
case 1:
dev = (i2cDev)((unsigned long)I2C1_BASE_ADDR);
break;
case 2:
dev = (i2cDev)((unsigned long)I2C2_BASE_ADDR);
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)I2C0_BASE_ADDR:
clksel = (PCLKSEL0>>14) & 3;
break;
case (int)I2C1_BASE_ADDR:
clksel = (PCLKSEL1>>6) & 3;
break;
case (int)I2C2_BASE_ADDR:
clksel = (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)I2C0_BASE_ADDR:
PCLKSEL0 |= clkselDec[pclkfactor]<<14;
PCLKSEL0 &= clkselDec[pclkfactor]<<14;
break;
case (int)I2C1_BASE_ADDR:
PCLKSEL1 |= clkselDec[pclkfactor]<<6;
PCLKSEL1 &= clkselDec[pclkfactor]<<6;
break;
case (int)I2C2_BASE_ADDR:
PCLKSEL1 |= clkselDec[pclkfactor]<<20;
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);
}
int i2cgetdatarate(i2cDev dev)
{
unsigned int dataRate=0;
unsigned int pclk = 0;
unsigned int cpuclk=0;
unsigned int i2csclkl=0;
if(dev==0)return 0;
cpuclk = coregetCpuFreq();
pclk = cpuclk / i2cgetpclkfactor(dev);
dataRate = pclk /( ((_i2cDev)dev)->I2SCLH + ((_i2cDev)dev)->I2SCLL);
return dataRate;
}