aboutsummaryrefslogtreecommitdiffstats
path: root/testhal/STM32/I2C/lis3.c
blob: b07a51f13a7263cfa8a341fe174e5bf0b62c79f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/**
 * This is most complex and difficult device.
 * It realize "read through write" paradigm. This is not standard, but
 * most of I2C devices use this paradigm.
 * You must write to device reading address, send restart to bus,
 * and then begin reading process.
 */

#include <stdlib.h>

#include "ch.h"
#include "hal.h"

#include "lis3.h"


// buffers
static i2cblock_t accel_rx_data[ACCEL_RX_DEPTH];
static i2cblock_t accel_tx_data[ACCEL_TX_DEPTH];

/* Error trap */
static void i2c_lis3_error_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){
  (void)i2cscfg;
  int status = 0;
  status = i2cp->id_i2c->SR1;
  while(TRUE);
}

// Accelerometer lis3lv02dq config
static I2CSlaveConfig lis3 = {
  NULL,
  i2c_lis3_error_cb,
  0,
  0,
  accel_rx_data,
  accel_tx_data,
  0b0011101,
  0,
  0,
  {NULL},
};





/**
 * This treading need for convenient realize
 * "read through write" process.
 */
static WORKING_AREA(I2CAccelThreadWA, 128);
static Thread *i2c_accel_tp = NULL;
static msg_t I2CAccelThread(void *arg) {
  (void)arg;

  int16_t acceleration_x = 0;
  int16_t acceleration_y = 0;
  int16_t acceleration_z = 0;

  I2CDriver *i2cp;
  msg_t msg;

  while (TRUE) {
    /* Waiting for wake up */
    chSysLock();
    i2c_accel_tp = chThdSelf();
    chSchGoSleepS(THD_STATE_SUSPENDED);
    msg = chThdSelf()->p_msg;    /* Retrieving the message, optional.*/
    chSysUnlock();

    /***************** Perform processing here. ***************************/
    i2cp = (I2CDriver *)msg;

    /* collect measured data */
    acceleration_x = lis3.rxbuf[0] + (lis3.rxbuf[1] << 8);
    acceleration_y = lis3.rxbuf[2] + (lis3.rxbuf[3] << 8);
    acceleration_z = lis3.rxbuf[4] + (lis3.rxbuf[5] << 8);
  }
  return 0;
}



/* This callback raise up when transfer finished */
static void i2c_lis3_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){
  (void) i2cscfg;

  // only wake up processing thread
  if (i2c_accel_tp != NULL) {
    i2c_accel_tp->p_msg = (msg_t)i2cp;
    chSchReadyI(i2c_accel_tp);
    i2c_accel_tp = NULL;
  }
}

/**
 * Init function. Here we will also start personal serving thread.
 */
int init_lis3(void){

  /* Starting the accelerometer serving thread.*/
  i2c_accel_tp = chThdCreateStatic(I2CAccelThreadWA,
                                  sizeof(I2CAccelThreadWA),
                                  HIGHPRIO,
                                  I2CAccelThread,
                                  NULL);

  /* wait thread statup */
  while (i2c_accel_tp == NULL)
    chThdSleepMilliseconds(1);

  lis3.rxbytes = 0; //set to 0 because we need only transmit

  /* configure accelerometer */
  lis3.txbytes = 4;
  lis3.txbuf[0] = ACCEL_CTRL_REG1 | AUTO_INCREMENT_BIT; // register address
  lis3.txbuf[1] = 0b11100111;
  lis3.txbuf[2] = 0b01000001;
  lis3.txbuf[3] = 0b00000000;

  /* sending */
  i2cMasterTransmit(&I2CD1, &lis3);
  chThdSleepMilliseconds(1);
  lis3.id_callback = i2c_lis3_cb;

  return 0;
}

/**
 *
 */
void request_acceleration_data(void){
  lis3.txbuf[0] = ACCEL_OUT_DATA | AUTO_INCREMENT_BIT; // register address
  lis3.txbytes = 1;
  lis3.rxbytes = 6;
  i2cAcquireBus(&I2CD1);
  i2cMasterTransmit(&I2CD1, &lis3);
  i2cReleaseBus(&I2CD1);
}