00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 #include <stdio.h>
00043 #include <signal.h>
00044 #include "contiki.h"
00045 #include "adxl345.h"
00046 #include "cc2420.h"
00047 #include "i2cmaster.h"
00048 
00049 
00050 extern void (*accm_int1_cb)(u8_t reg);
00051 extern void (*accm_int2_cb)(u8_t reg);
00052 
00053 
00054 static uint16_t int1_mask = 0, int2_mask = 0;
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 enum ADXL345_STATUSTYPES {
00064     
00065     INITED = 0x01,
00066     RUNNING = 0x02,
00067     STOPPED = 0x04,
00068     LOW_POWER = 0x08,
00069     AAA = 0x10,   
00070     BBB = 0x20,   
00071     CCC = 0x40,   
00072     DDD = 0x80,   
00073 };
00074 static enum ADXL345_STATUSTYPES _ADXL345_STATUS = 0x00;
00075 
00076 
00077 
00078 static uint8_t adxl345_default_settings[] = {
00079   
00080 
00081   
00082   ADXL345_THRESH_TAP,         
00083   ADXL345_THRESH_TAP_DEFAULT,
00084   ADXL345_OFSX_DEFAULT,
00085   ADXL345_OFSY_DEFAULT,
00086   ADXL345_OFSZ_DEFAULT,
00087   ADXL345_DUR_DEFAULT,
00088   ADXL345_LATENT_DEFAULT,
00089   ADXL345_WINDOW_DEFAULT,
00090   ADXL345_THRESH_ACT_DEFAULT,
00091   ADXL345_THRESH_INACT_DEFAULT,
00092   ADXL345_TIME_INACT_DEFAULT,
00093   ADXL345_ACT_INACT_CTL_DEFAULT,
00094   ADXL345_THRESH_FF_DEFAULT,
00095   ADXL345_TIME_FF_DEFAULT,
00096   ADXL345_TAP_AXES_DEFAULT,
00097 
00098   
00099   ADXL345_BW_RATE,    
00100   ADXL345_BW_RATE_DEFAULT,
00101   ADXL345_POWER_CTL_DEFAULT,
00102   ADXL345_INT_ENABLE_DEFAULT,
00103   ADXL345_INT_MAP_DEFAULT,
00104 
00105   
00106   ADXL345_DATA_FORMAT_DEFAULT,
00107   ADXL345_FIFO_CTL_DEFAULT
00108 };
00109 
00110 
00111 
00112 PROCESS(accmeter_process, "Accelerometer process");
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 void
00121 accm_write_reg(u8_t reg, u8_t val) {
00122   u8_t tx_buf[] = {reg, val};
00123 
00124   i2c_transmitinit(ADXL345_ADDR);
00125   while (i2c_busy());
00126   PRINTFDEBUG("I2C Ready to TX\n");
00127 
00128   i2c_transmit_n(2, tx_buf);
00129   while (i2c_busy());
00130   PRINTFDEBUG("WRITE_REG 0x%02X @ reg 0x%02X\n", val, reg);
00131 }
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 
00140 
00141 void
00142 accm_write_stream(u8_t len, u8_t *data) {
00143   i2c_transmitinit(ADXL345_ADDR);
00144   while (i2c_busy());
00145   PRINTFDEBUG("I2C Ready to TX(stream)\n");
00146 
00147   i2c_transmit_n(len, data);    
00148   while (i2c_busy());
00149   PRINTFDEBUG("WRITE_STR %u B to 0x%02X\n", len, data[0]);
00150 }
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159 u8_t
00160 accm_read_reg(u8_t reg) {
00161   u8_t retVal = 0;
00162   u8_t rtx = reg;
00163   PRINTFDEBUG("READ_REG 0x%02X\n", reg);
00164 
00165   
00166   i2c_transmitinit(ADXL345_ADDR);
00167   while (i2c_busy());
00168   i2c_transmit_n(1, &rtx);
00169   while (i2c_busy());
00170 
00171   
00172   i2c_receiveinit(ADXL345_ADDR);
00173   while (i2c_busy());
00174   i2c_receive_n(1, &retVal);
00175   while (i2c_busy());
00176 
00177   return retVal;
00178 }
00179 
00180 
00181 
00182 
00183 
00184 
00185 
00186 
00187 
00188 void
00189 accm_read_stream(u8_t reg, u8_t len, u8_t *whereto) {
00190   u8_t rtx = reg;
00191   PRINTFDEBUG("READ_STR %u B from 0x%02X\n", len, reg);
00192 
00193   
00194   i2c_transmitinit(ADXL345_ADDR);
00195   while (i2c_busy());
00196   i2c_transmit_n(1, &rtx);
00197   while (i2c_busy());
00198 
00199   
00200   i2c_receiveinit(ADXL345_ADDR);
00201   while (i2c_busy());
00202   i2c_receive_n(len, whereto);
00203   while (i2c_busy());
00204 }
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212 int16_t
00213 accm_read_axis(enum ADXL345_AXIS axis){
00214   int16_t rd = 0;
00215   u8_t tmp[2];
00216   if(axis > Z_AXIS){
00217     return 0;
00218   }
00219   accm_read_stream(ADXL345_DATAX0 + axis, 2, &tmp[0]);
00220   rd = (int16_t)(tmp[0] | (tmp[1]<<8));  
00221   return rd;
00222 }
00223 
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 
00235 void
00236 accm_set_grange(u8_t grange){
00237   if(grange > ADXL345_RANGE_16G) {
00238     
00239     PRINTFDEBUG("ADXL grange invalid: %u\n", grange);
00240     return;
00241   }
00242   u8_t tempreg = 0;
00243 
00244   
00245   tempreg = (accm_read_reg(ADXL345_DATA_FORMAT) & 0xFC);  
00246   tempreg |= grange;                                      
00247   accm_write_reg(ADXL345_DATA_FORMAT, tempreg);
00248 }
00249 
00250 
00251 
00252 
00253 
00254 void
00255 accm_init(void) {
00256   if(!(_ADXL345_STATUS & INITED)){
00257     PRINTFDEBUG("ADXL345 init\n");
00258     _ADXL345_STATUS |= INITED;
00259     accm_int1_cb = NULL;
00260     accm_int2_cb = NULL;
00261     int1_event = process_alloc_event();
00262     int2_event = process_alloc_event();
00263 
00264     
00265     ADXL345_DIR  &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN);
00266     ADXL345_SEL  &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN);
00267     ADXL345_SEL2 &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN);
00268 
00269     
00270     i2c_enable();
00271 
00272     
00273     accm_write_stream(15, &adxl345_default_settings[0]);
00274     accm_write_stream(5, &adxl345_default_settings[15]);
00275     accm_write_reg(ADXL345_DATA_FORMAT, adxl345_default_settings[20]);
00276     accm_write_reg(ADXL345_FIFO_CTL, adxl345_default_settings[21]);
00277 
00278     process_start(&accmeter_process, NULL);
00279 
00280     
00281     dint();
00282     ADXL345_IES &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN);   
00283     ADXL345_IE |= (ADXL345_INT1_PIN | ADXL345_INT2_PIN);     
00284     eint();
00285   }
00286 }
00287 
00288 
00289 
00290 
00291     
00292 void
00293 accm_set_irq(uint8_t int1, uint8_t int2){
00294   
00295   PRINTFDEBUG("IRQs set to INT1: 0x%02X IRQ2: 0x%02X\n", int1, int2);
00296 
00297   int1_mask = int1;
00298   int2_mask = int2;
00299 
00300   accm_write_reg(ADXL345_INT_ENABLE, (int1 | int2));
00301   accm_write_reg(ADXL345_INT_MAP, int2);  
00302 }
00303 
00304 
00305 #if 0
00306 
00307 
00308 
00309 
00310 
00311 
00312 static volatile clock_time_t ints_backoffs[] = {ADXL345_INT_OVERRUN_BACKOFF, ADXL345_INT_WATERMARK_BACKOFF,
00313                                                 ADXL345_INT_FREEFALL_BACKOFF, ADXL345_INT_INACTIVITY_BACKOFF,
00314                                                 ADXL345_INT_ACTIVITY_BACKOFF, ADXL345_INT_DOUBLETAP_BACKOFF,
00315                                                 ADXL345_INT_TAP_BACKOFF, ADXL345_INT_DATAREADY_BACKOFF};
00316 
00317 
00318 
00319 
00320 
00321 static clocktime_t
00322 backoff_passed(clocktime_t happenedAt, const clocktime_t backoff){
00323   if(timenow-lasttime >= backoff) {
00324     return 0;
00325   } else {
00326     return (timenow-lasttime);
00327   }
00328 }
00329 #endif
00330 
00331 
00332 
00333 
00334 
00335 
00336 static void
00337 poll_handler(void){
00338   uint8_t ireg = 0;
00339   ireg = accm_read_reg(ADXL345_INT_SOURCE);
00340   
00341 
00342   
00343   if(ireg & int1_mask){
00344     if(accm_int1_cb != NULL){
00345       PRINTFDEBUG("INT1 cb invoked\n");
00346       accm_int1_cb(ireg);
00347     }
00348   } else if(ireg & int2_mask){
00349     if(accm_int2_cb != NULL){
00350       PRINTFDEBUG("INT2 cb invoked\n");
00351       accm_int2_cb(ireg);
00352     }
00353   }
00354 }
00355 
00356 
00357 
00358 
00359 
00360 PROCESS_THREAD(accmeter_process, ev, data) {
00361   PROCESS_POLLHANDLER(poll_handler());
00362   PROCESS_EXITHANDLER();
00363   PROCESS_BEGIN();
00364   while(1){
00365     PROCESS_WAIT_EVENT_UNTIL(0);    
00366   }
00367   PROCESS_END();
00368 }
00369 
00370 
00371 
00372 
00373 
00374 #if 1
00375 static struct timer suppressTimer1, suppressTimer2;
00376 
00377 interrupt(PORT1_VECTOR) port1_isr (void) {
00378   ENERGEST_ON(ENERGEST_TYPE_IRQ);
00379   
00380   if ((ADXL345_IFG & ADXL345_INT1_PIN) && !(ADXL345_IFG & BV(CC2420_FIFOP_PIN))){
00381     
00382     if(timer_expired(&suppressTimer1)) {
00383       timer_set(&suppressTimer1, SUPPRESS_TIME_INT1);
00384       ADXL345_IFG &= ~ADXL345_INT1_PIN;   
00385       process_poll(&accmeter_process);
00386       LPM4_EXIT;
00387     }
00388   } else if ((ADXL345_IFG & ADXL345_INT2_PIN) && !(ADXL345_IFG & BV(CC2420_FIFOP_PIN))){
00389     
00390     if(timer_expired(&suppressTimer2)) {
00391       timer_set(&suppressTimer2, SUPPRESS_TIME_INT2);
00392       ADXL345_IFG &= ~ADXL345_INT2_PIN;   
00393       process_poll(&accmeter_process);
00394       LPM4_EXIT;
00395     }
00396   } else {
00397     
00398     if(cc2420_interrupt()) {
00399       LPM4_EXIT;
00400     }
00401   }
00402   ENERGEST_OFF(ENERGEST_TYPE_IRQ);
00403 }
00404 
00405 
00406 
00407 #endif