/*
Project: ADXL345 Demo
Functions: Page rotation, shake detection and single / double tap detection
Hardware platform: ADuC7026EVB and ADXL345EVB
Development tool: Keil UV3
Designed by: Nicolle Jia, CAST team, ADI
Version: V1.0
Data: 2008.5.29
*/
#include "ADuC7026.h"
#include "I2C_Master.h"
//Reigster of ADXL345
unsigned char DataX1, DataX2, DataY1, DataY2, DataZ1, DataZ2; //High byte and Low byte of Data register of X, Y, Z
unsigned int DataX, DataY, DataZ; //Word of Data register of X, Y, Z
unsigned char DevID; //Device ID
unsigned char Interrupt;
//Status; 01-Left, 02-Right, 03-Up, 04-Down, 05-Top, 06-Bottom, 08-Forward, 10-Backward, 20-Single Tap, 40-Double Tap
unsigned char RotateStatus, LastRotateStatus;
unsigned char TapStatus;
unsigned char ShakeStatus, LastShakeStatus, ShakeDetectStep;
//Counters
unsigned int RotateCounter;
unsigned int TapCounter;
unsigned int ShakeDetectCounter, ShakeStopCounter;
//Start flag
unsigned char IsStart;
//Uart put char, send Data directly
void PutChar( char Data)
{
COMTX=Data;
while(!(0x020==(COMSTA0 & 0x020))) {;}
}
//Uart display char, send HEX of Data
void DisplayChar( char Data)
{
unsigned char Temp;
Temp=Data>>4; //Send high byte
if(Temp<0x0A)
{
COMTX=0x30+Temp;
}
else
{
COMTX='\A'-0x0A+Temp;
}
while(!(0x020==(COMSTA0 & 0x020))) {;}
Temp=Data&0x0F; //Send low byte
if(Temp<0x0A)
{
COMTX=0x30+Temp;
}
else
{
COMTX='\A'-0x0A+Temp;
}
while(!(0x020==(COMSTA0 & 0x020))) {;}
}
//Uart interrupt service function, implement the communication with PC demo software
void IRQ_Handler() __irq
{
unsigned char UartDataReceived; // Received Data
unsigned char UartInterrupt; // Interrupt status
UartInterrupt =COMIID0 ;
if(UartInterrupt==0x04)//Has Received a Data
{
UartDataReceived=COMRX; //Get received data
if(UartDataReceived==0xAA) //Test connection by sending out device ID
{
COMTX=DevID;
}
if(UartDataReceived==0x55) //Start command
{
IsStart=0x01;
}
if(UartDataReceived==0xA5) //Stop command
{
IsStart=0x00;
}
}
/*
else if(UartInterrupt==0x02) // Has Send a Data
{
// Nothing to do
}
*/
}
//ADuC7026 UART initialization
void UART_Initiate()
{
// Setup tx & rx pins on P1.0 and P1.1
GP1CON = 0x2211; // I2C on P1.2 and P1.3 Setup tx & rx pins on P1.0 and P1.1 for UART
//Initiate the UART Port to 115200bps
POWKEY1 = 0x01; //Start PLL setting,changeless
POWCON=0x00;
POWKEY2 = 0xF4; //Finish PLL setting,changeless
COMCON0 = 0x80; // Setting DLAB
COMDIV0 = 0x0B; // Setting DIV0 and DIV1 to DL calculated
COMDIV1 = 0x00;
COMCON0 = 0x07; // Clearing DLAB
// fractional divider
COMDIV2 = 0x883E; // M=1
// N=01101010101 =853
// M+N/2048 =1.4165
//41.78MHz/(16*2*2^CD*DL*(M+N/2048)) //CD=0 DL=0B=11
//115.2Kbps M+N/2048 =1.0303 M=1, N= 62=0x3EH=000 0011 1110
//comdiv2=0x883E
//Enable UART interrupt
COMIEN0=0x03;
IRQEN = 0x4000;
}
//ADuC7026 I2C1 initialization
void I2C1_Initiate()
{
//Initiate the I2C1 Port to 400kbps
GP1CON = 0x2211; // I2C on P1.2 and P1.3 Setup tx & rx pins on P1.0 and P1.1 for UART
I2C1CFG = 0x82; // Master Enable & Enable Generation of Master Clock
// I2C-Master setup
I2C1DIV = 0x3232; // 0x3232 = 400kHz
// 0xCFCF = 100kHz
//Enable I2C1 Master Interupt
FIQEN |= SM_MASTER1_BIT;
}
//ADuc7026 initialization, UART and I2C1
void ADuC7026_Initiate(void)
{
UART_Initiate();
I2C1_Initiate();
}
//ADXL345 initialization, register configuration
void ADXL345_Initiate()
{
I2C_WRITE_REGISTER(0x2D,0x08); //Power CTL: Measure mode
I2C_WRITE_REGISTER(0x2C,0x0C); //Rate: 200Hz
I2C_WRITE_REGISTER(0x31,0x01); //Data Format: 8g right justified 128=1g
//I2C_WRITE_REGISTER(0x2E,0xE0); //Int En: Data Rdy, Single Tap, Doulbe Tap
I2C_WRITE_REGISTER(0x2E,0xE4); //Int En: Data Rdy, Single Tap, Doulbe Tap,Free fall
I2C_WRITE_REGISTER(0x2A,0x01); //Z Axis Tap
I2C_WRITE_REGISTER(0x1D,0x20); //Tap Threshold: 2G;
I2C_WRITE_REGISTER(0x28,0x09); //FreeFall Threshold: 300mg;
I2C_WRITE_REGISTER(0x29,0x14); //FreeFall Timing:100ms
I2C_WRITE_REGISTER(0x21,0x50); //Dur:50ms
I2C_WRITE_REGISTER(0x22,0x20); //Latent: 40ms
I2C_WRITE_REGISTER(0x23,0xF0); //Window: 300ms
}
//Delay
void Delay(unsigned int Time1, unsigned int Timer2)
{
unsigned int i, j, k=0xFFFF;
for(i=0;i<Time1;i++)
{
for(j=0; j<Timer2; j++)
while(k>0) k--;
}
}
void main(void)
{
ADuC7026_Initiate(); //ADuC7026 Initialization
ADXL345_Initiate(); //ADXL345 Initialization
//Variables initialization
IsStart=0x00;
//Variables for shake detection
ShakeStatus=0x00;
LastShakeStatus=0x00;
ShakeDetectStep=0x00;
ShakeDetectCounter=0;
ShakeStopCounter=0;
//Variables for Page Rotation
RotateStatus=0x00;
LastRotateStatus=0x00;
RotateCounter=0;
//Variables for Tap
TapStatus=0x00;
TapCounter=0;
DevID=(unsigned char)I2C_READ_REGISTER(0x00); //get device ID first
I2C_READ_REGISTER(0x30); //clear interrupt;
while(1) //Endless loop
{
if(IsStart==0x01) // Start
{
Interrupt=(unsigned char)I2C_READ_REGISTER(0x30); // get interrupt status
// Double Tap
//if((Interrupt&0x20)==0x20) //Double Tap interrupt
if((Interrupt&0x04)==0x04) //freefall interrupt
{
//if((RotateStatus==0x05) && (LastRotateStatus==0x05) ) // double tap function is available only when RotateStatus==Top
//{
//if(TapStatus==0x00) // no tap interrupt asserted before
//{
TapStatus=0x40; // double tap assert
TapCounter=0x00; // clear time counter,
PutChar(TapStatus); // send status to PC demo
//}
//}
}
else
{
if(TapCounter>=75) // wait for time counter overflow, then clear TapStatus,
{
TapStatus=0x00; // clear TapStatus
TapCounter=0x00; // clear time counter,
PutChar(TapStatus); // send status to PC demo
}
else TapCounter++;
}
//Single Tap, process method is similar with Double Tap
if((Interrupt&0x40)==0x40) //Single Tap interrupt,
{
if((RotateStatus==0x05) && (LastRotateStatus==0x05) )
{
if(TapStatus==0x00)
{
TapStatus=0x20;
TapCounter=0x00;
PutChar(TapStatus);
}
}
}
else
{
if(TapCounter>=75)
{
TapStatus=0x00;
TapCounter=0x00;
PutChar(TapStatus);
}
else TapCounter++;
}
if((Interrupt&0x80)==0x80) // Data Rdy interrupt, get X Y Z data for shake and rotate function
{
// Get high byte and low byte data of X Y Z, and combine into Word
DataX1=(unsigned char)I2C_READ_REGISTER(0x32);
DataX2=(unsigned char)I2C_READ_REGISTER(0x33);
DataY1=(unsigned char)I2C_READ_REGISTER(0x34);
DataY2=(unsigned char)I2C_READ_REGISTER(0x35);
DataZ1=(unsigned char)I2C_READ_REGISTER(0x36);
DataZ2=(unsigned char)I2C_READ_REGISTER(0x37);
DataX=DataX2;
DataX=(DataX<<8) | DataX1;
DataY=DataY2;
DataY=(DataY<<8) | DataY1;
DataZ=DataZ2;
DataZ=(DataZ<<8) | DataZ1;
//Rotate: Judgement methods for Right, left, Up, Down, Top, Bottom are same, only take "Down" for a detail example
// note that: the rotate status is related with the assemble direction of the ADXL345EVB
// Down: 0.7G < Y < 1.3G -0.5G < X <0.5G -0.5G < Z <0.5G
if( (DataY < 0xA6) && (DataY > 0x5A) && ((DataX <0x40) || (DataX >0xFFBF)) && ((DataZ <0x40) || (DataZ >0xFFBF)) )
{
if(LastRotateStatus==0x04)