From 044ad7c3987460ede48ff27afd6bdb0ca05a0432 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 4 Jul 2011 20:52:54 +0200 Subject: import at91lib from at91lib_20100901_softpack_1_9_v_1_0_svn_v15011 it's sad to see that atmel doesn't publish their svn repo or has a centralized location or even puts proper version/release info into the library itself --- utility/demo-fw/common/dfm_accelerometer.c | 647 +++++++++++++++++++++++++++++ 1 file changed, 647 insertions(+) create mode 100644 utility/demo-fw/common/dfm_accelerometer.c (limited to 'utility/demo-fw/common/dfm_accelerometer.c') diff --git a/utility/demo-fw/common/dfm_accelerometer.c b/utility/demo-fw/common/dfm_accelerometer.c new file mode 100644 index 0000000..410fe91 --- /dev/null +++ b/utility/demo-fw/common/dfm_accelerometer.c @@ -0,0 +1,647 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + //------------------------------------------------------------------------------ +/// \unit +/// +/// This file contains algorithms and drivers for tilt sensing. +/// +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ +#include "dfm_accelerometer.h" +#include "board.h" +#include +#include +#include +#include +#include + +#include + +#include + +#include "dfm_config.h" +#include "dfm_cmd.h" +#include "dfm_lcd_tsd.h" +#include "dfm_dispboxmgr.h" +#include "dfm_it.h" +#include "dfm_init.h" + +//------------------------------------------------------------------------------ +// Macros +//------------------------------------------------------------------------------ +#define BOARD_ADC12_FREQ 5000000 //! ADC clock +#define ADC12_VREF 3300 //! reference voltage 3.3 * 1000,make sure the jumper setting is right +#define PINS_ACC_ADC PIN_ADC0_AD2,PIN_ADC0_AD6,PIN_ADC0_AD7 + +#define TAN30 (37) //! fixed point for tanget tan(45)*0x40 +#define TAN15 17 //! fixed point for tangent tan(15)*0x40 +#define DELAY 100 +#define SAMPLES 1 + +#if defined(at91sam3u4) +#define AT91C_ID_ADC_PRESENT AT91C_ID_ADC12B +#define AT91C_BASE_ADC AT91C_BASE_ADC12B +#endif +//------------------------------------------------------------------------------ +// External Variables +//------------------------------------------------------------------------------ +extern const char * gpActiveBinFile; +extern unsigned int gLcdRefreshFlag; +extern int rotation_axes_cpt; +/// record measurement times +static int count =0; +//------------------------------------------------------------------------------ +// Variables +//------------------------------------------------------------------------------ + + +unsigned char ADC12_channel_x = ADC12_CHANNEL_2; //!< X Channel For Accelerometer +unsigned char ADC12_channel_y = ADC12_CHANNEL_6; //!< Y Channel For Accelerometer +unsigned char ADC12_channel_z = ADC12_CHANNEL_7; //!< Z Channel For Accelerometer +/// Indicates that the conversion is finished. +static volatile unsigned char conversionDone; + +acc_t acc = { //!< Accelerometer Instance + .m = { .x=0 , .y=0 , .z=0 } , + .k = { .x=ACC_ZERO_X , .y=ACC_ZERO_Y , .z=ACC_ZERO_Z } , + .ak = { .x=0 , .y=0 , .z=0 } , +} ; + +static const Pin pinsADC[] = {PINS_ACC_ADC}; + +static xyz_t lastMeasure = {0}; +int gDir = DIR_UNCHANGED; +int gLastDir = DIR_UNCHANGED; + +///push button to configure for the applicatino. +static Pin pinBP4 = PIN_PUSHBUTTON_1; +//------------------------------------------------------------------------------ +// Functions +//------------------------------------------------------------------------------ +int DV_Check_AccStatus(); + +//------------------------------------------------------------------------------ +/// add position +//------------------------------------------------------------------------------ +xyz_t xyz_add (xyz_t p, xyz_t q) +{ + xyz_t r ; + r.x = p.x + q.x ; + r.y = p.y + q.y ; + r.z = p.z + q.z ; + return r ; +} + +//------------------------------------------------------------------------------ +/// sub position +//------------------------------------------------------------------------------ +xyz_t xyz_diff (xyz_t p, xyz_t q) +{ + xyz_t r ; + r.x = p.x - q.x ; + r.y = p.y - q.y ; + r.z = p.z - q.z ; + return r ; +} + +//------------------------------------------------------------------------------ +/// Invoke platform api to get converted data +/// \param pAdc address pointer for ADC12B controller +/// \param ADC12_channel_x channel number for x axis +/// \param ADC12_channel_y channel number for y axis +/// \param ADC12_channel_z channel number for z axis +/// \return converted data for three channels +//------------------------------------------------------------------------------ +xyz_t acc_get_value ( AT91S_ADC12B *pAdc , unsigned char ADC12_channel_x, unsigned char ADC12_channel_y, unsigned char ADC12_channel_z) +{ + xyz_t val ; + + val.x = ADC12_GetConvertedData(pAdc, ADC12_channel_x); + val.y = ADC12_GetConvertedData(pAdc, ADC12_channel_y); + val.z = ADC12_GetConvertedData(pAdc, ADC12_channel_z); + + val.x = val.x>>ACC_SHIFT; + val.y = val.y>>ACC_SHIFT; + val.z = val.z>>ACC_SHIFT; + + return val ; +} + + +//------------------------------------------------------------------------------ +/// get present acceleration value as 0-g value for x and y, 1-g value for z +//------------------------------------------------------------------------------ +void DoCalibration() +{ + int i = 0,j; + xyz_t temp ={0}; + count = 0; + acc.m.x = 0; + acc.m.y = 0; + acc.m.z = 0; + for(i = 0; i < 16 ; i++) + { + if(DV_Check_AccStatus()){ + temp = xyz_add(acc.m,temp); + for(j=0;j (TAN15*TAN15)*(y*y+z*z) || (unsigned int)(y*y)<<12 > (TAN15*TAN15)*(x*x+z*z)) + { + if((unsigned int)(x*x)<<12 > (TAN15*TAN15)*(y*y+z*z)) + { + if((unsigned int)(y*y)<<12 > (TAN15*TAN15)*(x*x+z*z)) + { + if(x < 0) + { + if(y < 0) + { + dir = DV_Accelerometer_up_right; + } + else + { + dir =DV_Accelerometer_down_right; + } + } + else + { + if(y < 0) + { + dir = DV_Accelerometer_up_left; + } + else + { + dir = DV_Accelerometer_down_left; + + } + } + } + else + { + if(x < 0) + { + dir = DV_Accelerometer_right; + } + else + { + dir = DV_Accelerometer_left; + } + } + + } + else + { + if(y < 0) + { + dir = DV_Accelerometer_up; + } + else + { + dir = DV_Accelerometer_down; + } + } + } + + return dir; + +} + + +//------------------------------------------------------------------------------ +/// get the direction of the board +/// \return direction +//------------------------------------------------------------------------------ +int DV_Accelerometer_Dir() +{ + + int dir = gDir; + int x=0,y=0,z=0; + xyz_t diff = {0}; + + ///measure the difference between the last one and the present one + diff = xyz_diff(acc.m,lastMeasure); + + ///check the status,acc.m will be changed after called routine + ///if conversion is done,otherwise,return immediately + DV_Check_AccStatus(); + + + ///no big change since last measurement + if( diff.x*diff.x + diff.y*diff.y + diff.z*diff.z < ((ACC_1G*ACC_1G)>>11)) + { + ///keep the old direction + return gDir; + + } + ///update lastMeasure to the new one + lastMeasure = acc.m; + + ///get acceleration offset + acc.ak = xyz_diff(acc.m,acc.k); + + + + x = acc.ak.x; + y = acc.ak.y; + z = (acc.ak.z + ACC_1G); + /// filter non-tilting operation + if( (x*x + y*y+z*z > ACC_AMPLITUDE_UPPER) ||(x*x + y*y+z*z < ACC_AMPLITUDE_LOWER) ){ + return gDir; + } + + ///the board plane is angled with the horizontal surface + if( (unsigned int)(x*x)<<12 > (TAN30*TAN30)*(y*y+z*z) || (unsigned int)(y*y)<<12 > (TAN30*TAN30)*(x*x+z*z)) + { + + if(x*x > y*y + (y*y>>1)) + { + if(x > 0) + { + dir = DIR_HORIZIONTAL_UP; + } + else + { + dir = DIR_HORIZIONTAL_DOWN; + } + } + else if(x*x + (x*x>>1) < y*y) + { + if(y > 0) + { + dir = DIR_VERTICAL_UP; + } + else + { + dir = DIR_VERTICAL_DOWN; + } + } + //else dir = previous dir + //leave gap enough for stabilization + ///renew the direction + gDir = dir; + } + + return gDir; + +} +//------------------------------------------------------------------------------ +/// Check accelerometer is ready? +/// if the direction is unchanged since last measurement,return "not ready" +/// \return 0 not ready, other value means ready and command string length +//------------------------------------------------------------------------------ +unsigned int ACC_CommandIsReady() +{ + int dir = DIR_UNCHANGED; + unsigned int ret; + dir = DV_Accelerometer_Dir(); + //no change of direction since last measurement + if(gLastDir == dir) + { + ret = 0; + } + else + { + ret = 1; + } + gLastDir = dir; + return ret; +} + + +//------------------------------------------------------------------------------ +// get flipped ppt page +//------------------------------------------------------------------------------ +const char * ACC_GetCommand() +{ + if(gDir == DIR_HORIZIONTAL_UP || gDir == DIR_HORIZIONTAL_DOWN) + { + //update to portait image file + gpActiveBinFile = LCDSLIDEVIMAGEFILE; + gLcdRefreshFlag = 1; + + } + else + { + gpActiveBinFile = LCDSLIDEIMAGEFILE; + gLcdRefreshFlag = 1; + + } + return NULL; +} + +//an example of ShowPrompt +int ACC_ShowPrompt() +{ +// int i; +// switch(gDir)//gDir +// { +// +// case DIR_HORIZIONTAL_UP: +// printf("Horizontal Up!\n"); +// //LCDD_DrawRectangle((void *)BOARD_LCD_BASE, x,y,width,height,0xE0E0C0); +// break; +// case DIR_HORIZIONTAL_DOWN: +// printf("Horizontal Down!\n"); +// break; +// case DIR_VERTICAL_UP: +// printf("Vertical Up!\n"); +// break; +// case DIR_VERTICAL_DOWN: +// printf("Vertical Down!\n"); +// break; +// default: +// printf("Unchanged!\n"); +// break; +// } +// for(i=0;i<5000;i++); + return 0; +} + +//global accelerometer entry variable +TInputEntry gAccEntry = {0, {NULL,NULL},ACC_ShowPrompt, ACC_CommandIsReady, ACC_GetCommand, NULL}; +//------------------------------------------------------------------------------ +/// Check if conversion is done.If done,read the corresponding parameters and +///start new measurement +//------------------------------------------------------------------------------ +int DV_Check_AccStatus() +{ + //check if conversation is done + //if done, read and measure,and start new conversation + //else, return directly + + + if(conversionDone == ((1<