ini
[aversive.git] / modules / devices / encoders / encoders_spi / encoders_spi.c
1 /*  
2  *  Copyright Droids Corporation (2009)
3  * 
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  *  Revision : $Id: encoders_spi.c,v 1.1.2.3 2009-04-07 20:00:46 zer0 Exp $
19  *
20  *  Olivier MATZ <zer0@droids-corp.org>
21  */
22
23 /* This modules handles encoders: values are read through a SPI
24  * interface. Basically, frames are formatted with 4 words of 16 bits,
25  * describing the values of the 4 encoders. */
26
27 #include <string.h>
28
29 #include <aversive.h>
30 #include <aversive/parts.h>
31
32 #include <spi.h>
33
34 #include <encoders_spi.h>
35 #include <encoders_spi_config.h>
36
37 static int32_t g_encoders_spi_values[ENCODERS_SPI_NUMBER];
38 static int16_t g_encoders_spi_previous[ENCODERS_SPI_NUMBER];
39
40
41 /* Initialisation of encoders, variables */
42 void encoders_spi_init(void)
43 {
44         memset(g_encoders_spi_previous, 0, sizeof(g_encoders_spi_previous));
45         spi_register_ss_line(&ENCODERS_SPI_SS_PORT, ENCODERS_SPI_SS_BIT);
46         spi_init(SPI_MODE_MASTER, ENCODERS_SPI_FORMAT, ENCODERS_SPI_CLK_RATE);
47         spi_set_data_order(ENCODERS_SPI_DATA_ORDER);
48         encoders_spi_manage(NULL);
49         memset(g_encoders_spi_values, 0, sizeof(g_encoders_spi_values));
50 }
51
52
53 /* Update encoders values */
54 void encoders_spi_manage(__attribute__((unused)) void *dummy)
55 {
56         union {
57                 struct {
58                         uint8_t u8_lsb;
59                         uint8_t u8_msb;
60                 } s;
61                 int16_t s16;
62         } enc;
63         uint8_t i;
64         int16_t diff;
65         uint8_t flags;
66
67         spi_slave_select(0);
68         for (i=0; i<ENCODERS_SPI_NUMBER; i++) {
69                 enc.s.u8_lsb = spi_receive_byte();
70                 enc.s.u8_msb = spi_receive_byte();
71                 diff = enc.s16 - g_encoders_spi_previous[i];
72                 g_encoders_spi_previous[i] = enc.s16;
73                 IRQ_LOCK(flags);
74                 g_encoders_spi_values[i] += diff;
75                 IRQ_UNLOCK(flags);
76         }
77         spi_slave_deselect(0);
78 }
79
80
81
82 /* Extract encoder value */
83 int32_t encoders_spi_get_value(void *encoder)
84 {
85         int32_t value;
86         uint8_t flags;
87
88         IRQ_LOCK(flags);
89         value = g_encoders_spi_values[(int)encoder];
90         IRQ_UNLOCK(flags);
91
92         return value;
93 }
94
95 /* Set an encoder value */
96 void encoders_spi_set_value(void *encoder, int32_t val)
97 {
98         uint8_t flags;
99
100         IRQ_LOCK(flags);
101         g_encoders_spi_values[(int)encoder] = val;
102         IRQ_UNLOCK(flags);
103 }