traj circle
[aversive.git] / modules / devices / encoders / encoders_eirbot / encoders_eirbot.c
1 /*  
2  *  Copyright Droids Corporation, Microb Technology, Eirbot (2005)
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_eirbot.c,v 1.4.4.3 2007-05-23 17:18:13 zer0 Exp $
19  *
20  */
21
22 /** \file encoders_eirbot.c
23  *  \brief achieves acess to incremental encoderss through a xilinx interface
24  *
25  *  \todo nothing !
26  *
27  *  \test  
28  *
29  *  this modules reads 8 bit encoders values on an external interface.
30  *  there are two necessary busses with the interface logic: 8 bit data bus and a n bits selection bus.
31  *  ( see the VDHL for the xilinx program)
32  *  with n bits on the selection bus, you can acess to 2^n encoderss.
33  *
34  *  modifié par lamygale le 10 octobre 2005. d'apres le code 2004 du codeur
35  *
36  */
37
38
39
40 #include <aversive.h>
41
42
43 #include "encoders_eirbot.h"
44
45 #include "encoders_eirbot_config.h"
46
47 #ifdef ENCODERS_MODE_XILINX
48 // mask for selection bits
49 #define ENCODERS_SELEC_MASK ((0xFF >> (8-ENCODERS_SELEC_NITS_NUM)) \
50                                  << ENCODERS_SELEC_BIT0)
51 #define ENCODERS_DATA_MASK ((0xFF >> (8-ENCODERS_DATA_NBBITS)) \
52                                  << ENCODERS_DATA_BIT0)
53 // bits qui ne sont pas des donnees sont a 1 (donnees sont alignees a droite)
54 #define DIFF_DATA_MASK ((0xFF >> ENCODERS_DATA_NBBITS) << ENCODERS_DATA_NBBITS)
55
56 volatile encoders g_codeur_valeurs[ENCODERS_NUMBER];
57
58 volatile int8_t g_codeur_preced[ENCODERS_NUMBER];
59
60
61
62 /**
63  * fonction utilisée 2 fois seulement, acquiert un codeur
64 */
65 inline int8_t get_codeur(uint8_t num)
66 {
67   int8_t val;
68   uint8_t flags;
69
70   IRQ_LOCK(flags);
71
72   ENCODERS_SELEC_PORT =   ( ENCODERS_SELEC_PORT & (~ENCODERS_SELEC_MASK)  ) | ( num << ENCODERS_SELEC_BIT0);
73
74   nop(); // delay for IO & xilix delay time
75   nop();
76
77   val = (ENCODERS_PIN & ENCODERS_DATA_MASK) >> ENCODERS_DATA_BIT0;
78
79   IRQ_UNLOCK(flags);
80
81   return val;
82 }
83
84 /** Initialisation des codeurs, variables, et ports */
85 void encoders_init(void)
86 {
87   uint8_t number;
88   uint8_t flags;
89
90   IRQ_LOCK(flags);
91
92   ENCODERS_SELEC_DDR |= ENCODERS_SELEC_MASK;   // port de selection en sortie
93   ENCODERS_DATA_DDR  &= (~ENCODERS_DATA_MASK); // port de donnees en entree 
94
95   for(number = 0 ; number < ENCODERS_NUMBER; number ++)
96     {
97       g_codeur_valeurs[number] = 0;
98       g_codeur_preced[number] = get_codeur(number);
99     }
100   
101   IRQ_UNLOCK(flags);
102 }
103
104 /** mise a jour des valeurs des codeurs, a faire réguliereement minimum  a la fréquence (Fmax_codeur/127) */
105 void encoders_manage(void)
106 {
107   uint8_t number;
108   int8_t res, lu;
109   uint8_t nombre_a_ajouter;  // pour gerer les nombres négatifs
110   uint8_t flags;
111
112   for(number = 0 ; number < ENCODERS_NUMBER; number ++)
113     { 
114
115       lu = get_codeur(number); // lecture
116       res = lu - g_codeur_preced[number]; // calcul diff
117       g_codeur_preced[number] = lu;  // mise a jour ancienne valeur 
118
119       // on recopie l'etat du MSb dans les bits != donnees 
120       nombre_a_ajouter = ((res >> (ENCODERS_DATA_NBBITS - 1))&1) ? DIFF_DATA_MASK : 0; // si MSb = 1, on prend mask
121       res = (res & ~DIFF_DATA_MASK) + nombre_a_ajouter; // bits de poids faibles = donnees, les autres = signe
122
123       IRQ_LOCK(flags);
124       g_codeur_valeurs[number] += res;
125       IRQ_UNLOCK(flags);
126     }
127 }
128
129 /** Extraction d'une valeur de codeur */
130 encoders encoders_get_value(uint8_t number)
131 {
132   encoders value;
133   uint8_t flags;
134
135   IRQ_LOCK(flags);
136   value = g_codeur_valeurs[number];
137   IRQ_UNLOCK(flags);
138
139   return value;
140 }
141
142 #else
143 #error the irq version of the codeur module is not implemented yet
144 #endif